package com.signway.swmediaplayerdemo;

import static com.signway.swmediaplayerdemo.MainActivity.VIDEO;
import static com.signway.swmediaplayerdemo.MainActivity.getVideoPath;
import static com.signway.swmediaplayerdemo.MainActivity.getVideoPathList;
import static com.signway.swmediaplayerdemo.MainActivity.hideBottomUIMenu;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.os.signway.SignwayManager;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Choreographer;
import android.view.Display;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.RelativeLayout;
import android.widget.Toast;

import com.SubtitleTest;
import com.signway.ffmpeg.FFmpeg;
import com.signway.swmediaplayer.SWMediaPlayer;
import com.signway.swmediaplayer.utils.SystemProperties;
import com.signway.swmediaplayerdemo.databinding.ActivityMediaBinding;
import com.signway.swmediaplayerdemo.view.TextView3;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Calendar;
import java.util.Random;

public class MediaActivity extends AppCompatActivity {
    private static final String TAG = MediaActivity.class.getName();
    private ActivityMediaBinding binding;

    private SignwayManager sm;

    private boolean isPause = false;
    private SWMediaPlayer mSWMediaPlayer = null;

    private int MODE = SWMediaPlayer.MEDIA_COMPLETION_PAUSE;

    private int videoWidth = 0;
    private int videoHeight = 0;
    private long mLastRenderTimestampNs = 0;

    private static final int CMD_START = 0;
    private static final int CMD_RESTART = 1;
    private static final int CMD_SHOW_IMG = 2;
    private static final int CMD_PREPARE = 3;
    private static final int CMD_HIDE_IMAGE = 4;

    private MediaFormat mediaFormat = new MediaFormat();
    public static final String VIDEO_FORMAT = "video/";
    public static final String AUDIO_FORMAT = "audio/";

    private SubtitleTest mSubtitleTest = new SubtitleTest();

    private HandlerThread handlerThread = null;
    private MediaPlayerHandler mHandler = null;

    public class MediaPlayerHandler extends Handler {
        MediaPlayerHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(@NonNull Message msg) {
            Log.d(TAG, "handleMessage: " + msg.what);
            switch (msg.what) {
                case CMD_START:
                    mSWMediaPlayer.start();
                    break;
                case CMD_RESTART:
                    Log.d(TAG, "switch player start " + (mLastRenderTimestampNs - System.nanoTime()));
                    MainActivity.VideoRes res = getVideoPath();
                    if (res.type == VIDEO) {
                        initPlayer(mSWMediaPlayer, binding.surface4k.getHolder(), res.path);
                    }
                    try {
                        mSWMediaPlayer.prepare();
                    } catch (IOException | InterruptedException e) {
                        e.printStackTrace();
                    }
                    Log.d(TAG, "switch player finish");
                    break;
                case CMD_HIDE_IMAGE:
                    binding.image.setVisibility(View.GONE);
                    break;
                case CMD_SHOW_IMG:
                    Log.d(TAG, "handleMessage: CMD_SHOW_IMG");
//                    binding.image.setVisibility(View.INVISIBLE);
                    if (MODE == SWMediaPlayer.MEDIA_COMPLETION_PAUSE)
                        mHandler.sendEmptyMessageDelayed(CMD_START, 8000);
                    else if (MODE == SWMediaPlayer.MEDIA_COMPLETION_STOP)
                        mHandler.sendEmptyMessageDelayed(CMD_RESTART, 8000);
                    break;
            }
        }
    }

    @SuppressLint("SdCardPath")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityMediaBinding.inflate(getLayoutInflater());

        handlerThread = new HandlerThread("mediaplayer");
        handlerThread.start();
        mHandler = new MediaPlayerHandler(handlerThread.getLooper());

        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(binding.getRoot());
        hideBottomUIMenu(this);

        MODE = getIntent().getIntExtra("MODE", MODE);

        binding.surface4k.getHolder().setFormat(PixelFormat.TRANSPARENT);
        binding.surface4k.getHolder().addCallback(new SurfaceCallBack(this, mSWMediaPlayer));
        binding.surface4k.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        if (MODE != SWMediaPlayer.MEDIA_COMPLETION_STOP) {
            String[] videoList = getVideoPathList();
            int maxInputSize = 0;
            for (int i = 0; i < videoList.length; i++) {
                MediaExtractor mediaExtractor = new MediaExtractor();
                try {
                    Log.d(TAG, "setDataSource : " + videoList[i]);
                    mediaExtractor.setDataSource(videoList[i]);
                    for (int j = 0; j < mediaExtractor.getTrackCount(); j++) {
                        MediaFormat format = mediaExtractor.getTrackFormat(j);
                        String mime = format.getString(MediaFormat.KEY_MIME);
                        if (mime.startsWith(VIDEO_FORMAT)) {
                            if (format.containsKey(MediaFormat.KEY_MAX_INPUT_SIZE)) {
                                Log.d(TAG, videoList[i] + ", InputSize " + format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE));
                                maxInputSize = Math.max(format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE), maxInputSize);
                            }
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    mediaExtractor.release();
                }
            }
            if (maxInputSize > 0) {
                mediaFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, maxInputSize);
                Log.d(TAG, "maxInputSize: " + maxInputSize);
            }
        }

        MainActivity.VideoRes res = getVideoPath();
        if (res.type == VIDEO) {
            initPlayer(mSWMediaPlayer, binding.surface4k.getHolder(), res.path);
        }

        sm = getSystemService(SignwayManager.class);
        WindowManager windowManager = getWindow().getWindowManager();
        DisplayMetrics metrics = new DisplayMetrics();
        windowManager.getDefaultDisplay().getRealMetrics(metrics);
        int width = metrics.widthPixels;
        int height = metrics.heightPixels;
        Log.d(TAG, "width " + width + ", height " + height);
        mSubtitleTest.init(sm, width, height);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mHandler.removeCallbacksAndMessages(null);
        handlerThread.quitSafely();
        mSubtitleTest.release();
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        mHandler.removeCallbacksAndMessages(null);
        if (mSWMediaPlayer != null) {
            mSWMediaPlayer.release();
            mSWMediaPlayer = null;
        }
        finish();
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        Log.d(TAG, "onKeyDown: keyCode" + keyCode);
        switch (keyCode) {
            case KeyEvent.KEYCODE_F8:
            case KeyEvent.KEYCODE_F7:
            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
            case KeyEvent.KEYCODE_MEDIA_NEXT:
                /* 如果当前为暂停状态内部会执行播放流程 */
                if (mSWMediaPlayer != null)
                    mSWMediaPlayer.switchDataSource();
                isPause = false;
                binding.mediaPause.setText("暂停");
                break;
            case KeyEvent.KEYCODE_F9:
            case KeyEvent.KEYCODE_MEDIA_PAUSE:
                if (!isPause) {
                    isPause = true;
                    if (mSWMediaPlayer != null)
                        mSWMediaPlayer.pause();
                    binding.mediaPause.setText("播放");
                }
                break;
            case KeyEvent.KEYCODE_ENTER:
            case KeyEvent.KEYCODE_MEDIA_PLAY:
                if (isPause) {
                    isPause = false;
                    if (mSWMediaPlayer != null)
                        mSWMediaPlayer.start();
                    binding.mediaPause.setText("暂停");
                }
                break;
        }
        return super.onKeyDown(keyCode, event);
    }

    private SWMediaPlayer.OnPreparedListener mOnPreparedListener = mp -> {
        Log.d(TAG, "setOnPreparedListener");
         mp.start();
    };

    private SWMediaPlayer.OnInfoListener mOnInfoListener = (mp, what, extra) -> {
        if (what == SWMediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) {
            Log.d(TAG, "MEDIA_INFO_VIDEO_RENDERING_START");

            if (MODE == SWMediaPlayer.MEDIA_COMPLETION_PAUSE) {
                mHandler.sendEmptyMessage(CMD_HIDE_IMAGE);
            }

            if (MODE == SWMediaPlayer.MEDIA_COMPLETION_STOP) {
                Log.d(TAG, "setLayoutParams " + videoWidth + ", " + videoHeight);
            }
        } else if (what == SWMediaPlayer.MEDIA_INFO_VIDEO_RENDERING_END) {
            Log.d(TAG, "MEDIA_INFO_VIDEO_RENDERING_END");
            if (MODE == SWMediaPlayer.MEDIA_COMPLETION_STOP) {
                mHandler.sendEmptyMessage(CMD_RESTART);
            }
        }
        return true;
    };

    private SWMediaPlayer.OnCompletionListener mOnCompletionListener = new SWMediaPlayer.OnCompletionListener() {
        @Override
        public int onCompletion(SWMediaPlayer mp, long lastRenderTimestampNs) {
            mLastRenderTimestampNs = lastRenderTimestampNs;
            Log.d(TAG, "setOnCompletionListener " + ((mLastRenderTimestampNs - System.nanoTime()) / 1000_000));

            MainActivity.VideoRes res;
            switch (MODE) {
                case SWMediaPlayer.MEDIA_COMPLETION_PAUSE:// --> start
                    res = getVideoPath();
                    if (res.type == VIDEO) {
                        try {
                            mp.setNextFilePath(res.path);/* 设置下一个视频文件 */
                            Log.d(TAG,  "mPlayer.getDuration() " + mp.getDuration());
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    mHandler.sendEmptyMessageDelayed(CMD_SHOW_IMG,  40 + ((mLastRenderTimestampNs - System.nanoTime()) / 1000_000));
                    break;
                case SWMediaPlayer.MEDIA_COMPLETION_CONTINUE:// --> reset
                    res = getVideoPath();
                    if (res.type == VIDEO) {
                        try {
                            mp.setNextFilePath(res.path);/* 设置下一个视频文件 */
                            Log.d(TAG,  "mPlayer.getDuration() " + mp.getDuration());
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    break;
            }

            binding.mediaSwitch.setClickable(true);

            return MODE;
        }
    };

    private SWMediaPlayer.OnVideoSizeChangedListener mOnVideoSizeChangedListener = (mp, width, height) -> {
        if (mSWMediaPlayer != null) {
            videoWidth = width;
            videoHeight = height;
        }
    };

    private void initPlayer(SWMediaPlayer mPlayer, SurfaceHolder holder, String path) {
        if (mPlayer != null) {
            long startMs = SystemClock.elapsedRealtime();
            mPlayer.release();
            Log.d(TAG, "mPlayer.release() timems " + (SystemClock.elapsedRealtime() - startMs));
        }
        mSWMediaPlayer = null;

        mSWMediaPlayer = new SWMediaPlayer();
        mSWMediaPlayer.setOnPreparedListener(mOnPreparedListener);
        mSWMediaPlayer.setOnInfoListener(mOnInfoListener);
        mSWMediaPlayer.setOnCompletionListener(mOnCompletionListener);
        mSWMediaPlayer.setOnVideoSizeChangedListener(mOnVideoSizeChangedListener);
        mPlayer = mSWMediaPlayer;

        try {
            mPlayer.reset();
            mPlayer.setDataSource(path);
            mPlayer.setDisplay(holder);
            mPlayer.setScreenOnWhilePlaying(true);

            MediaFormat mediaFormat = new MediaFormat();
            mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 25);
            mPlayer.setCustomFormat(mediaFormat);

            Log.d(TAG,  "mPlayer.getDuration() " + mPlayer.getDuration());
        } catch (Exception e) {
            e.printStackTrace();
            mPlayer.release();
            Toast.makeText(this, "无法播放", Toast.LENGTH_LONG).show();
        }
    }

    private class SurfaceCallBack implements SurfaceHolder.Callback {
        private Context mContext;

        public SurfaceCallBack(Context context, SWMediaPlayer player) {
            mContext = context;
        }

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            Log.d(TAG, "surfaceCreated " + holder.toString());
            try {
                mSWMediaPlayer.prepare();
            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            Log.d(TAG, "surfaceChanged width " + width + ", height" + height);
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            Log.d(TAG, "surfaceDestroyed");
        }
    }
}